from django.db import transaction
from rest_framework import serializers
from goods.models import SKU
from .models import OrderInfo,OrderGoods
from django.utils import timezone
from decimal import Decimal
from django_redis import get_redis_connection
class OrderPlaceSerializer(serializers.ModelSerializer):
    count = serializers.IntegerField(min_value=1,label="数量")
    class Meta:
        model = SKU
        fields = ("default_image_url","name","price","count","id")


class OrderCommitSerializer(serializers.ModelSerializer):
    class Meta:
        model = OrderInfo
        fields = ("address","pay_method","order_id")

        read_only_fields = ["order_id"] #序列化的时候,(也就是返回的时候用,反序列化的时候不用)

        #write_only, 反序列化的时候用, 序列化的时候不用
        extra_kwargs = {
            "address":{
                "write_only":True
            },
            "pay_method":{
                "write_only":True
            }
        }

    #1,重写create方法,去出redis数据,创建订单对象, 订单商品对象
    @transaction.atomic
    def create(self, validated_data):

        #1,获取user
        user = self.context["request"].user

        #2,创建订单编号(尽量保证唯一性)
        order_id = timezone.now().strftime("%Y%m%d%H%M%S") + "%06d"%user.id

        #3,获取地址
        address = validated_data["address"]

        #4,获取支付方式
        pay_method = validated_data["pay_method"]

        #5,订单状态
        if pay_method == OrderInfo.PAY_METHODS_ENUM["CASH"]:
            status = OrderInfo.ORDER_STATUS_ENUM["UNPAID"]
        else:
            status = OrderInfo.ORDER_STATUS_ENUM["UNSEND"]

        #TODO 设置保存点
        sid = transaction.savepoint()

        #6,创建订单信息对象
        order = OrderInfo.objects.create(
            order_id = order_id,
            user = user,
            address = address,
            total_count = 0,
            total_amount = Decimal(0.0),
            freight = Decimal(10.0),
            pay_method = pay_method,
            status = status,
        )

        #7,获取redis中数据
        redis_conn = get_redis_connection("cart")
        cart_dict = redis_conn.hgetall("cart_%s"%user.id)
        cart_selected_list = redis_conn.smembers("cart_selected_%s"%user.id)

        #8,遍历创建订单商品对象
        for sku_id in cart_selected_list:
            while True:
                #8.1获取商品对象,数量
                sku = SKU.objects.get(id=sku_id)
                count = int(cart_dict[sku_id])

                #8.2判断库存量是否足够
                if count > sku.stock:
                    #TODO 回滚
                    transaction.savepoint_rollback(sid)
                    raise serializers.ValidationError("库存不足")

                #TODO 模拟并发下单
                import time
                time.sleep(5)

                #8.3减少库存,增加销量
                # sku.stock -= count
                # sku.sales += count
                # sku.save()

                # TODO 使用乐观锁,解决并发下单问题
                old_stock = sku.stock
                old_sales = sku.sales
                new_stock = old_stock - count
                new_sales = old_sales + count

                ret =  SKU.objects.filter(id=sku_id,stock=old_stock).update(stock=new_stock,sales=new_sales)

                if ret == 0:
                    # raise serializers.ValidationError("下单失败")
                    continue #继续查询一次库存

                #8.4累加商品数量和价格
                order.total_count += count
                order.total_amount += (sku.price * count)

                #8.5创建订单商品对象
                OrderGoods.objects.create(
                    order=order,
                    sku=sku,
                    count=count,
                    price=sku.price,
                )
                break #必须退出

        #9,保存,清除redis数据
        order.save()
        transaction.savepoint_commit(sid) #TODO 提交
        redis_conn.hdel("cart_%s"%user.id,*cart_selected_list)
        redis_conn.srem("cart_selected_%s"%user.id,*cart_selected_list)

        #10,返回响应
        return order